﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Notoric.Model.Validation
{
    /// <summary>
    /// The exception that is thrown when an attempt is made to set a property to an invalid value.
    /// </summary>
    /// <remarks>
    /// The validation rules that were broken can be retrieved from the <see cref="Exception.Data"/> property
    /// under the "BrokenRules" key or through the <see cref="BrokenRules"/> property.
    /// </remarks>
    [Serializable]
    public class ValidationException : Exception
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="ValidationException"/> instance.
        /// </summary>
        public ValidationException() { }

        /// <summary>
        /// Creates a new <see cref="ValidationException"/> instance.
        /// </summary>
        /// <param name="message">
        /// <para>
        /// Type: <see cref="System.String"/>
        /// </para>
        /// <para>
        /// The message that describes the error.
        /// </para>
        /// </param>
        public ValidationException(string message)
            : base(message) { }

        /// <summary>
        /// Creates a new <see cref="ValidationException"/> instance.
        /// </summary>
        /// <param name="propertyName">
        /// <para>
        /// Type: <see cref="System.String"/>
        /// </para>
        /// <para>
        /// Name of the property that was set to an invalid value
        /// </para>
        /// </param>
        /// <param name="brokenRules">
        /// <para>
        /// Type: <see cref="System.Array"/> of <see cref="Rule"/>
        /// </para>
        /// <para>
        /// Collection of the broken validation rules
        /// </para>
        /// </param>
        public ValidationException(string propertyName, Rule[] brokenRules)
            : base("The value for the " + propertyName + " property is not valid!")
        {
            Data.Add("BrokenRules", brokenRules);
        }

        /// <summary>
        /// Creates a new <see cref="ValidationException"/> instance.
        /// </summary>
        /// <param name="message">
        /// <para>
        /// Type: <see cref="System.String"/>
        /// </para>
        /// <para>
        /// The message that describes the error.
        /// </para>
        /// </param>
        /// <param name="inner">
        /// <para>
        /// Type: <see cref="Exception"/>
        /// </para>
        /// <para>
        /// The exception that is the cause of the current exception, or <see langword="null"/> if no inner exception is specified.
        /// </para>
        /// </param>
        public ValidationException(string message, Exception inner)
            : base(message, inner) { }

        /// <summary>
        /// Creates a new <see cref="ValidationException"/> instance.
        /// </summary>
        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
        protected ValidationException(SerializationInfo info, StreamingContext context)
            : base(info, context) { }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the collection of broken validation rules.
        /// </summary>
        public Rule[] BrokenRules
        {
            get { return (Rule[])Data["BrokenRules"]; }
        }

        #endregion
    }
}
